<?php

namespace App\Models\User\AcceleratorPacks;

use App\Models\Task\SnapTasks\Repositories\Interfaces\SnapTaskRepositoryInterface;
use App\Models\Task\SnapTasks\SnapTask;
use App\Trip\Traits\ModelDateTrait;
use Carbon\Carbon;
use Eloquent;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;

/**
 * App\Models\User\AcceleratorPacks\UserAcceleratorPacks
 *
 * @property int                             $id
 * @property string                          $user_id    用户id
 * @property string                          $channel    获取渠道 1 助力获得 2 其他
 * @property string                          $date       格式 Ymd 每个用户每天有上限，用户统计
 * @property int                             $count      加速包数量
 * @property int                             $state      状态 0 待使用 1 已使用
 * @property string                          $expired_at 过期日期
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @method static Builder|UserAcceleratorPack newModelQuery()
 * @method static Builder|UserAcceleratorPack newQuery()
 * @method static Builder|UserAcceleratorPack query()
 * @method static Builder|UserAcceleratorPack whereChannel($value)
 * @method static Builder|UserAcceleratorPack whereCount($value)
 * @method static Builder|UserAcceleratorPack whereCreatedAt($value)
 * @method static Builder|UserAcceleratorPack whereDate($value)
 * @method static Builder|UserAcceleratorPack whereExpiredAt($value)
 * @method static Builder|UserAcceleratorPack whereId($value)
 * @method static Builder|UserAcceleratorPack whereState($value)
 * @method static Builder|UserAcceleratorPack whereUpdatedAt($value)
 * @method static Builder|UserAcceleratorPack whereUserId($value)
 * @mixin Eloquent
 */
class UserAcceleratorPack extends Model
{
    use HasFactory, ModelDateTrait;


    const CHANNEL_ASSIST = 1;

    protected $table = 'user_accelerator_packs';
    protected $fillable
                     = [
            "user_id",
            "channel",
            "date",
            "count",
            "state",
            "expired_at",
        ];


    /**
     * @throws Exception
     */
    public function addPack(array $data): self
    {
        $data['state']      = 0;
        $data['expired_at'] = Carbon::today()->addYear()->toDateString();
        $count              = $data['count'];
        $pack_key           = "UserAcceleratorPacks:addPack:{$data['date']}:{$data['user_id']}";
        if (Cache::has($pack_key)) {
            if (Cache::get($pack_key) > 10) {
                throw new Exception("您当日5次助力次数已满");
            }
        } else {
            if (!Cache::has($pack_key)) {
                Cache::put($pack_key, 0, config('trip.ttl.day'));
            }
            Cache::increment($pack_key, $count);
        }

        return $this->create($data);
    }

    public function usePackBySelfTask(SnapTask $task, string $user_id)
    {
        if ($task->isPaidHighLevel()) {
            return;
        }

        $max_count     = $task::MAX_ASSIST_COUNT;
        $can_use_ids   = $this->where('user_id', $user_id)
                              ->where('state', 0)
                              ->orderBy('id')
                              ->where('expired_at', '>=', Carbon::now()->toDateTimeString())
                              ->pluck('id')->toArray();
        $can_use_count = count($can_use_ids);
        $can_use_count = min($can_use_count, $max_count);
        if ($can_use_count > 0) {
            $this->where('user_id', $user_id)
                 ->where('state', 0)
                 ->where('expired_at', '>=', Carbon::now()->toDateTimeString())
                 ->orderBy('id')
                 ->whereIn('id', $can_use_ids)
                 ->limit($can_use_count)
                 ->update([
                     'state' => 1,
                 ]);
            $task_repo = app(SnapTaskRepositoryInterface::class);
            $task_repo->updateTaskSnapAssistCountAndLevelBySelfPacks($task, $can_use_count);
        }
    }
}
